#ifndef IMPLTCPSOCKET_H
#define IMPLTCPSOCKET_H

#include "tcpsocket.h"
#include <iostream>
#include <winsock2.h>
#include <thread>
#include <mutex>
#include <atomic>
#include <condition_variable>

class TcpSocket::Impl
{
public:
    Impl();
    ~Impl();

    static int startup();
    static int cleanup();

    void setBufferSize(unsigned int size);
    unsigned int readBufferSize() const;

    bool connectToHost(std::string host, unsigned short port);
    void abort();
    bool state() const { return connFlag_; }

    int write(const char *data, int len);

    unsigned int read(char *data, unsigned int maxlen);
    std::string read(unsigned int maxlen);
    std::string readAll() { return read(dataSize_); }

    unsigned int bytesAvailable() const { return dataSize_; }
    bool isReadyRead() const { return readyRead_; }
    bool waitForReadyRead(int msecs);

    void registerReadyReadSig(std::function<void ()> callback);

private:
    bool _isReadyRead();

private:
    std::atomic<SOCKET> socket_;
    std::atomic_bool connFlag_;
    std::atomic_bool readyRead_;
    std::atomic_uint bufferSize_; // max size
    std::atomic_uint dataSize_; // read size
    std::unique_ptr<char[]> buffer_;
    std::mutex mtx_;
    std::condition_variable cv_;
    std::thread th_;
    bool about_;
    std::function<void()> fnReadyRead_;
};

#endif // IMPLTCPSOCKET_H
